home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 39.2 KB | 1,307 lines | [TEXT/MPS ] |
- %
- % File: FillProcs.ps
- %
- % Contains: This file contains Procedures the procedures used for Skia clips and fills.
- %
- % Version: Technology: Quickdraw GX 1.1.x.
- %
- % Copyright: © 1991-7 by Apple Computer, Inc., all rights reserved.
- %
- %
-
-
- % File contains the following Procedures:
- % ShapeBuildChar (Internally referenced only)
- % MakeShapeFont (Internally referenced only)
- % PatternFill (Internally referenced only)
- % MakePatternDict
- % QD2Fill
- % QD2Clip
- % QD2Show
- % DashStroke
- % MakeDashDict
- %
- % Also contains dictionaries (PatternFillDict, FillDict, ClipDict)
- % which contain the procedures for the various types of Skia fills.
-
-
-
-
-
- %<FF>
- %
- % First we need procedures for patterns:
- %
- %
- languagelevel 2 lt {
- % The shape buildchar procedure, draws the shape for a font. Only done in Level-1
- %
- % Set up the font cache.
- % Use the FontBBox for the cache and ux, uy for the advance
- % Execute the geometry
- % Execute the paint operator
- %
- % fontDict glyphCode ShapeBuildChar -
- %
- % fontDict: The pattern font's dictionary.
- % glyphCode: The id of the character to draw, we don't really care what character, however.
- %
- /ShapeBuildChar {
-
- pop % We don't care what the glyph code is.
- begin % Put the font dictionary at top of stack.
-
- 0 setlinewidth % If it is framed, it is always hairline. (Skia definition)
-
- Shape begin % Put shape dictionary on stack.
-
- % Set up the font cache.
- AdvanceVector dup 0 get exch 1 get % Advance width for font cache.
-
- shapeType /i ne { % If it is not a deep bitmap pattern
-
- x1 y1 Grid x2 y2 Grid setcachedevice % set up the cache bounding box.
- geomProc % Execute the geometry
- FillDict fillKey get exec % Paint it. (superfluous for 1-bit bitmaps but check would be extra work)
-
- } { % Else
-
- setcharwidth % Just set up advance widths.
- geomProc % Execute the shape (paints itself)
-
- } ifelse
-
- end
-
- end
-
- } Bdef
-
- } {
-
- %% Paint procedure for level-2 pattern dictionaries.
-
- /PatternPaintProc {
-
- begin % Make the pattern dictionary the current top dictionary.
-
- IpatTransform concat % Transform CTM by inverse pattern matrix.
-
- patShape begin % Put shape dictionary on the dict stack.
-
- CurrColorSet % Save the old color set on the stack.
-
- colorSet SetColorSet % Get the shape's color set, make it current.
- ColorSpace null ne { % If the shape has a level-2 color space (should never have both colorSet and space)
-
- ColorSpace GXSetCSpace % set it
-
- } if
-
- shapeType /b eq { % For one bit bitmap patterns, deal with foreground/background color
-
- CurrOrMode 0 eq { % If not or mode, draw rectangle in background color
-
- 0 colorSet SetIndexedColor % Set color to background color.
- newpath
- x1 y1 moveto x2 y1 lineto
- x2 y2 lineto x1 y2 lineto
- closepath
- fill
-
- } if
-
- ImageMaskColor colorSet SetIndexedColor % set the color to the ImageMask color
-
- } if
-
- newpath % Make sure there is no current path.
- geomProc % Execute the geometry procedure.
-
- FillDict fillKey get exec % Paint it with the proper fill procedure for the fill type.
-
- SetColorSet % Restore the old colorset.
-
- end
-
- end
-
- } Bdef
-
- } ifelse % level 1 or level 2
-
-
- %<FF>
- %
- % Procedure: MakeShapeFont
- % Makes a type-3 font describing for drawing a geometry. used for level-1 patterns.
- %
- % shape ux uy MakeShapeFont dict
- %
- % shape: A valid shape dictionary
- % ux, uy: The x and y components of the U vector in the pattern.
- %
- languagelevel 2 lt { % Only needed for level 1.
-
- /MakeShapeFont {
-
- 8 dict dup begin % Make a dictionary, put it on the dict stack, save a copy.
-
- 4 1 roll % Put duplicate dictionary at bottom of the stack.
-
- [3 1 roll]
- /AdvanceVector Xdef % Save ux, uy in an array so we can write into it.
-
- /Shape Xdef
-
- %
- % Now Define required entries in the font dictionary.
- %
- /FontType 3 def
- /FontMatrix [1 0 0 1 0 0] def % The pattern should be in correct space.
-
- /FontBBox [ % The bounding box
- Shape ShapeBBox
- ] def
-
- /Encoding StandardEncoding def % Just becuase it's a required entry, won't use it.
-
- /BuildChar /ShapeBuildChar load def
-
- end
-
- } Bdef
-
- } if % level-1 only
-
-
-
-
- %<FF>
- %
- % Function checks a matrix to see if it a scale only (no rotation - except 90, 180, 270 -
- % no skewing, translation allowed)
- %
- % matrix IsMatrixJustScaling matrix justscale
- %
- % matrix: input matrix (left on stack after execution behind boolean)
- % justScale: Boolean, true if matrix is just scaling, false otherwise
- %
- /IsMatrixJustScaling {
-
- % Check diagonals of *********
- % * a b 0 *
- % * c d 0 *
- % * e f 1 *
- % *********
-
- dup 0 get % Stack is: matrix a
- 1 index 3 get % Stack is: matrix a d
- 0.0 eq exch 0.0 eq and % Stack is: matrix FirstDiagonalEqual
-
- 1 index 1 get % Stack is: matrix FirstDiagonalEqual b
- 2 index 2 get % Stack is: matrix FirstDiagonalEqual b c
- 0.0 eq exch 0.0 eq and % Stack is: matrix FirstDiagonalEqual SecondDiagonalEqual
- or % Stack is: matrix matrixJustScaled
-
- } Bdef
-
- %
- % Watch out for rentrancy problems here if patterns
- % can ever go recursive (ie pattern could be shape with pattern)
- % these globals could get mucked up.
- /PortMapping matrix def
- /PortPatternMapping matrix def % Port Mapping to be used for the pattern.
- /SaveCTMForPattern matrix def % Save the CTM
-
-
- %
- % Function grids a matrix if it is only a scale matrix (90 degree rotations allowed)
- % Used for PortPatternMapping to ensure integer scaling of patterns
- %
- /GridMatrix {
-
- IsMatrixJustScaling { % If the matrix is just a scaling matrix.
-
- % If the matrix is not rotated or skewed then round off the scaling.
-
- 0 1 3 { % Just the first 4 elements of the matrix.
-
- dup % Stack is matrix index index
- 2 index exch % Stack is matrix index matrix index
- get dup abs 1.0 gt { % Only round for scales > 1
- round % Stack is matrix index round(matrix[index])
- } if
- 2 index % Stack is matrix index round(matrix[index]) matrix
- 3 1 roll put % Stack is matrix
-
- } for
-
- } if
-
- pop % Pop off extra copy of matrix.
-
- } Bdef
-
-
-
- %<FF>
- %
- % Routine ensures that a matrix that looks like it should really be
- % non-scaling is non-scaling. We do this because sometimes round
- % off error on high resolution printers makes matrices that should
- % cause device resolution drawings are somtimes off by a small amount
- % This throws postscript bitmap rendering into the slow case, and the
- % reason we are doing the stuff as device resolution bitmaps is for speed.
- %
- /EnsureDeviceResolution {
-
- ScratchMatrix currentmatrix IsMatrixJustScaling {
-
- % If the scale components are near 1, make them 1.
- 0 1 3 { % Loop on first 4 elements of matrix. (everything but translation values)
-
- dup 2 index exch % Get the element of the matrix
- get dup abs 1.0 sub abs .005 le { % Is the component near 1.0 (within 0.5%)?
-
- % Force value to be 1.0, signed same as original.
-
- 0.0 lt {
- -1.0
- } {
- 1.0
- } ifelse
-
- } if
-
- 2 index 3 1 roll put % Put the new value in the matrix
-
- } for
-
- } if
-
- % Stack contains either unmodified matrix or adjusted one, either way:
- setmatrix
-
- } Bdef
-
- %
- % Procedure: SetupPatternCTM
- % Procedure sets up the CTM for the rendering of the pattern based upon the
- % PortMap and PortAllign attributes. Old CTM is saved in SaveCTMForPattern
- % Only Rob Johnson can explain the whole reason why the CTMs are translated this way.
- %
- % The pattern must be on the dictionary stack.
- % SetupPatternCTM -
- %
- /SetupPatternCTM {
-
- SaveCTMForPattern currentmatrix pop
-
- PortMap { % If port Map is true (must be a bitmap pattern)
-
- PortMapping PortPatternMapping
- copy dup GridMatrix % Grid the matrix for bitmap patterns.
- setmatrix % Make the current space the port space.
- PortAllign not { % If not port alligned then translate appropriately.
-
- % Get location of shape 0,0 in current (port) space and allign to it.
-
- 0 0 SaveCTMForPattern transform itransform
- translate
-
- } if
-
- } { % Else PortMap is false
-
- PortAllign { % If PortAllign is true, then translate the CTM
-
- % Get location of port 0,0 is in user space and allign to it.
-
- 0 0 PortMapping transform itransform
- translate
-
- } if
-
- } ifelse
-
- } Bdef
-
-
- % Procedure MakePatternDict:
- % Procedure makes a valid pattern dictionary for the PatternFill operator.
- % It computes the pattern matrices based upon the lattice parameters.
- %
- % shape ux uy vx vy px py PortMap PortAllign MakePatternDict dict
- %
- % shape: A valid shape dictionary
- % ux, uy: The u vector from the pattern record.
- % vx, vy: The v vector from the pattern record.
- % px, py: The phase of the pattern. (Skia currently doesn't do this, pass 0, 0)
- % PortMap Boolean, gxPortMapPattern on or off.
- % PortAllign Boolean, gxPortAlignPattern on or off.
- % dict: Created, a valid pattern dictionary.
- %
- languagelevel 2 lt {
- /MakePatternDict {
-
- 21 dict dup begin % Make the dictionary and leave it on the stack
-
- 10 1 roll % Roll the duplicate dictionary back before the parameters.
-
- /PortAllign Xdef
- /PortMap Xdef
- /py Xdef /px Xdef
- /vy Xdef /vx Xdef
- /uy Xdef /ux Xdef
-
- /patTransform [ % Make the matrix from parameters.
-
- ux uy
- vx vy
- px py
-
- ] def
-
- % Stack is shape:
- % If the shape is a 1-bit bitmap (/b) and the lattice is different from the bitmap's dimensions
- % Change the shape type to image (/i) to prevent patternfill from doing a fill of the background
- % color - /i makes Draw1bitBitmapString do it instead on a per stamp basis.
-
- dup /shapeType get /b eq {
-
- dup ShapeBBox % Stack is: shape x1 y1 x2 y2
- BoxWidths % Stack is: shape width height
-
- vy ne vx 0 ne or % Stack is: shape width (height!=vy || vx!=0)
- exch ux ne uy 0 ne or % Stack is: shape (width!=ux || uy!=0) (height!=vy || vx!=0)
- or { % If either is true, change shapeType.
-
- dup /shapeType /i put
-
- } if
-
- } if
-
- % Stack is left: shape, ready to make the font, Get advance width for the character.
-
- ux uy MakeShapeFont % Make a font out of the pattern shape using the u vector as advance.
-
- /patternFont exch definefont % Give the font the name "patternFont" It may have to be unique,
- % If we find this out later, I'll fix it.
-
- /patternFontDict Xdef % Save the font dictionary in the pattern dictionary.
-
- /IpatTransform % Get the inverse of the matrix
- patTransform matrix
- invertmatrix
- def
-
- end
-
- } Bdef
-
- } { %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% level-2 version of MakePatternDict.
-
- /MakePatternDict {
-
- 10 dict dup begin % Make the dictionary and leave it on the stack
-
- 10 1 roll % Roll the duplicate dictionary back before the parameters.
-
- /PatternType 1 def % 1 is what the book says to use.
- /PortAllign Xdef % Get PortAllign boolean.
- /PortMap Xdef % Get PortMap boolean.
- [ 7 1 roll ] % Make the matrix
- /patTransform Xdef % Save it in the dictionary
-
- /XStep 1 def % Run through the pattern transform yields Skia's U and V.
- /YStep 1 def
-
- /TilingType CurrGridFit {2} {1} ifelse def % Base it on grid fit from style.
-
- /PaintProc /PatternPaintProc load def % Get a copy of the pattern procedure.
-
- /IpatTransform % Get the inverse of the matrix
- patTransform [0 0 0 0 0 0]
- invertmatrix
- def
-
- /patShape Xdef % Save the shape dictionary.
-
- %
- % Get the tightest bounding box, this is very performance criticle.
- % small errors can make big speed hits.
- % e.g: if bbox is just 2x as big, speed hit is 3-4x.
- %
- /BBox [
-
- gsave
-
- ScratchMatrix currentmatrix % Save the current matrix on the stack.
- IpatTransform concat % Concatonate the inverse pattern matrix.
-
- patShape /shapeType get /g eq { % If it is a geometric shape then:
-
- patShape /geomProc get exec % execute the geometry procedure.
- setmatrix % put the matrix back.
- /flattenpath 0 AvoidLimit pathbbox % Get the tight bounding box.
-
- } { % else
-
- patShape ShapeBBox % Get bounding box from shape dictionary.
- 4 2 roll 4 copy 4 2 roll BoxWidths RP % Make it into a path.
- pop pop
- setmatrix % Restore the CTM
- pathbbox % Get bounding box of transformed rectangle.
-
- } ifelse
-
- grestore
-
- ] def
-
- %
- % Assign the paint type based on the shape type
- %
- /PaintType
-
- %% bitmap patterns are colored patterns.
-
- patShape /shapeType get dup /i eq exch /b eq or { % If it is bitmap then
- 1 % painttype is colored pattern.
- } { % else
- 2 % painttype is uncolored pattern.
- }ifelse
-
- def
-
- end
-
- dup /patTransform get % Get the transform to pass to makepattern
- makepattern % Just make the pattern
-
- } Bdef
-
- } ifelse % level-1 or level-2
-
-
-
-
-
-
- %<FF>
- %
- % Fill the current path with the pattern described by the dictionary.
- %
- % Only needed for level-1.
- % boolean patternDict PatternFill -
- %
- % boolean: true means winding-number, false means even-odd
- % pattermDict: a valid pattern dictionary.
-
- languagelevel 2 lt {
-
- %
- /patternString 100 string def % Allocate a hundred byte string for pattern stamping.
-
- /PatternFill {
-
- CurrPat begin % Put the pattern dict at top of dict stack
-
- gsave % Save the current clip and CTM - we'll muck with it to fill with the pattern.
-
- SetupPatternCTM % Fix up user space for PortAllign and PortMap
-
- % The boolean is on the stack to Determine even-odd fill or winding-number fill.
-
- % If it is a bitmap pattern, handle the colorset, don't have to worry about space, this is a level-1 proc only:
-
- patternFontDict /Shape get /shapeType get /b eq {
-
- CurrOrMode 0 eq { % if not or-mode, fill the shape with background color
-
- 0 patternFontDict /Shape get /colorSet get SetIndexedColor % set color to background.
-
- dup % duplicate the boolean for even-odd
- gsave {fill} {eofill} ifelse grestore % fill the shape
-
- } if
-
- ImageMaskColor patternFontDict /Shape get /colorSet get SetIndexedColor % Set color to Image Mask color.
-
- } { % If the shape, otherwise has a colorSet (only indexed bitmaps should) install it.
-
- patternFontDict /Shape get /shapeType get /i eq {
-
- patternFontDict /Shape get dup /colorSet get dup % Stack is shapeDict shapeDict colorSet colorSet
-
- null ne { % If the colorset is not null
-
- SetColorSet % Set the colorSet if it has one.
-
- /BitsPerPixel get 2 exch exp 1 sub /MaxSampleInt exch store % Get bits/pixel from shape, Set the maxSample
-
- InstallColorSetTransfers % They will be de-installed by the grestore at the end of PatternFill
-
- } {
-
- pop % Pop off the duplicate shape dictionary
- pop % Pop off the null from duplicating the colorSet entry in the shape dictionary
-
- } ifelse
-
- } if
-
- } ifelse
-
- {/clip 0 AvoidLimit}
- {/eoclip 0 AvoidLimit}
- ifelse % Make the current path the clip based on boolean
-
- /flattenpath 0 AvoidLimit % Make sure we get an accurate bounding box
- /pathbbox load stopped % Get the current path bounding box on the stack
- {0 0 0 0} if % if pathbbox failed just put a 0 bounding box on the stack.
- % It fails on things like "0 0 moveto 0 0 rlineto strokepath"
- newpath % Don't leave flattened path around, it takes up valuable path room
-
- % Now stack is x1 y1 x2 y2 (The fill path's bounding box)
-
- patternFontDict dup setfont % Make patternFont current font
- /FontBBox get % get the bbox
- {} forall BoxWidths % How wide is the pattern?
-
- % Stack is now x1 y1 x2 y2 Wx Wy
- 6 2 roll % Stack is now Wx Wy x1 y1 x2 y2
-
- % Expand the current path's box by the width of the pattern:
-
- % Stack:
- 4 index add % Wx Wy x1 y1 x2 (y2 + Wy)
- exch % Wx Wy x1 y1 (y2 + Wy) x2
- 5 index add % Wx Wy x1 y1 (y2 + Wy) (x2 + Wx)
- 4 2 roll % Wx Wy (y2 + Wy) (x2 + Wx) x1 y1
- 4 index sub % Wx Wy (y2 + Wy) (x2 + Wx) x1 (y1 - Wy)
- exch % Wx Wy (y2 + Wy) (x2 + Wx) (y1 - Wy) x1
- 5 index sub % Wx Wy (y2 + Wy) (x2 + Wx) (y1 - Wy) (x1 - Wx)
-
- exch 4 2 roll exch % Wx Wy (x1 - Wx) (y1 - Wy) (x2 + Wx) (y2 + Wy)
-
- /y2 Xdef
- /x2 Xdef
- /y1 Xdef
- /x1 Xdef
-
- % Find the bounding box in pattern space.
- % x1' = Min of X coordinates of all 4 corners.
- % x2' = Max of X coordinates of all 4 corners.
- % y1' = Min of Y coordinates of all 4 corners.
- % y2' = Max of Y coordinates of all 4 corners.
-
- x1 y1 IpatTransform transform pop % Get x' component of vector (x1,y1)
- x1 y2 IpatTransform transform pop % Get x' component of vector (x1,y2)
- Min % Which one is smaller?
-
- x2 y1 IpatTransform transform pop % Get x' component of vector (x2,y1)
- x2 y2 IpatTransform transform pop % Get x' component of vector (x2,y2)
- Min % Which one is smaller?
-
- Min floor /x1p Xdef % Get smallest of all 4.
-
- x1 y1 IpatTransform transform pop % Get x' component of vector (x1,y1)
- x1 y2 IpatTransform transform pop % Get x' component of vector (x1,y2)
- Max % Which one is bigger?
-
- x2 y1 IpatTransform transform pop % Get x' component of vector (x2,y1)
- x2 y2 IpatTransform transform pop % Get x' component of vector (x2,y2)
- Max % Which one is bigger?
-
- Max ceiling /x2p Xdef % Get biggest of all 4.
-
- x1 y1 IpatTransform transform exch pop % Get y' component of vector (x1,y1)
- x2 y1 IpatTransform transform exch pop % Get y' component of vector (x2,y1)
- Min % Which one is smaller?
-
- x1 y2 IpatTransform transform exch pop % Get y' component of vector (x1,y2)
- x2 y2 IpatTransform transform exch pop % Get y' component of vector (x2,y2)
- Min % Which one is smaller?
-
- Min floor /y1p Xdef % Get smallest of all 4.
-
- x1 y1 IpatTransform transform exch pop % Get y' component of vector (x1,y1)
- x2 y1 IpatTransform transform exch pop % Get y' component of vector (x2,y1)
- Max % Which one is Bigger?
-
- x1 y2 IpatTransform transform exch pop % Get y' component of vector (x1,y2)
- x2 y2 IpatTransform transform exch pop % Get y' component of vector (x2,y2)
- Max % Which one is bigger?
-
- Max ceiling /y2p Xdef % Get biggest of all 4.
-
- /x1p x1p floor def
- /y1p y1p floor def
- /x2p x2p ceiling def
- /y2p y2p ceiling def
-
- pop pop % Get rid of the widths.
-
-
-
- % Now stamp the pattern across the lattice defined by the bounding box in pattern space.
-
- % Calculate the width of the pattern lattice
- /lattWidth x2p x1p sub 1 add cvi def
-
- % Walk the lattice vertically
- y1p 1 y2p {
-
- x1p exch patTransform transform moveto % Move to the next position in the lattice.
-
- 0 100 lattWidth { % As many times as it takes for width given string size.
-
- lattWidth exch sub % How much of this scan is left to stamp?
- dup 100 gt { % If it is bigger than the string then
- pop 100 % current length is string length
- } if % else we can do as many as we asked for
- patternString 0 3 -1 roll getinterval % Get a substring no bigger than we need.
- show % show it.
-
- } for
-
- } for
-
- grestore
- newpath
-
- end
-
- } Bdef
-
- } if % defined for level 1 only.
-
-
- %<FF>
- % Procedure PathLength:
- % Procedure finds the length of the current path, leaves the path flattened.
- %
- % - PathLength L
- %
- % L is length of path, left on stack.
- %
- /PathLength {
-
- /@1 0 def % initialize the length.
-
- { /@3 Xstore /@2 Xstore } % moveto procedure, @2 is X, @3 is Y
-
- { 2 copy % lineto procedure:
- @3 sub dup mul % Get (y2-y1)^2
- exch @2 sub dup mul % Get (x2-x1)^2
- add sqrt % Get length of vector
- @1 add /@1 Xdef % Accumulate total length.
- /@3 Xstore /@2 Xstore % Get new x1, y1
- }
- {} % curveto procedure, assumes path is flattened.
- {} % closepath procedure.
-
- /flattenpath 0 AvoidLimit % Flatten the path.
-
- pathforall
-
- @1 % Leave length on stack.
-
- } Bdef
-
-
- %<FF>
- % Procedure MakeDashDict:
- % Procedure makes a valid dash dictionary for the DashStroke operator.
- %
- % shape autoAdvance level breakDash advance phase scale MakeDashDict dict
- %
- % shape: A valid shape dictionary
- % autoAdvance boolean, autoAdvance on or off.
- % levelDash: boolean, level-dash on or off.
- % breakDash: boolean, break-dash on or off.
- % advance: The advance of the dash.
- % phase: The phase of the dash.
- % scale: The scale of the dash.
- %
- % dict: Created, a valid pattern dictionary.
- %
- /MakeDashDict {
-
- 16 dict begin % Make the dictionary and leave it on the stack
-
- /dashScale Xdef % Virtual scaling for dash shape.
- /phase Xdef % Phase of the dash
- /advance Xdef % Get the advance of the dash
- /breakDash Xdef % Get the break-dash bit.
- /levelDash Xdef % Get the level-dash bit.
- /autoAdvance Xdef % Get the autoAdvance bit.
-
- /Shape Xdef % Get the shape.
-
- Shape ShapeBBox % Compute the X center of the shape
- pop exch pop 2 copy sub 2 div % Stack is: x1 x2 -width
- neg exch pop add % Stack is: x1+width
- /xCenter Xdef % Store the xCenter.
-
- /FirstX null def /FirstY 0 def % These are used by the DashStroke operator.
- /LastX 0 def /LastY 0 def
-
- /CurrCTM matrix def % We need to save the CTM someplace during dashing.
- /N 0 def % Place holder for number of dashes on contour for autoAdvance.
-
- currentdict % Leave a copy of the dash-dictionary on the stack.
- end
-
- } Bdef
-
-
-
- %<FF>
- % This procedure draws the dash shape in the proper scale and orientation on the path.
- %
- /StampDash {
-
- % Grid fit the positions to avoid PS stupid round off error when contour is on pixel wide.
-
- LastX FirstX NotEqual
- LastY FirstY NotEqual or { % If the length of the contour is non-zero then
-
- CurrDash % Save current dash dictionary on stack.
- currentlinewidth % Save the current line width on the stack.
- null SetDash % Turn off dashing while we render the dash shape to avoid recursive application of dash
- CurrCTM currentmatrix % Save the CTM, leave copy on stack.
-
- FirstX FirstY translate % move the origin to the point to draw the dash.
-
- levelDash not { % if level-dash is disabled, rotate the CTM by the tangent of the path.
-
- LastY FirstY sub % Do rotation based on arc-tangent of path.
- LastX FirstX sub
- ATanRot
-
- } if
-
- 1 currentlinewidth scale % Scale Only in Y direction by pen width
- 0 setlinewidth % Make sure framed dashes are hairlines.
- 0 frameOffset translate % Do translation for inside or outside frame fill.
- 1 1 dashScale div scale % Scale the pen by the line 1/scale
-
- breakDash { % If break-dash is on, translate by the center like Skia does.
- xCenter neg 0 translate
- } if
-
- newpath 0 0 moveto
- Shape begin % Put shape dictionary on dict stack.
- geomProc % Execute the dash geometry in transformed space
- setmatrix % Restore the transform so patterns in the dash aren't transformed.
- fillKey QD2Fill % Paint the dash shape.
- end
-
- setlinewidth % Restore the line width.
- SetDash % Restore the dash dictionary.
-
-
- } if
-
- } Bdef
-
- % The following is the set of procedures required for framing an object with a dash dictionary.
- % The first 4 are the parameters to the pathforall operator.
- %
- % The lineto and curveto procedures update the last x,y point, the closepath proc does nothing.
- %
- /DashLT {/LastY Xdef /LastX Xdef} Bdef
- /DashCT {/LastY Xdef /LastX Xdef 4 {pop} repeat } Bdef
- /DashCP {} Bdef
-
- %
- % The moveto proc is the big one. If we are at a real moveto (not one that simply moves
- % to the same point as the last x,y) then we calculate the tangent and the scale
- % And draw the dash shape.
- %
- /DashMT {
-
- FirstX null eq { % If it was the first time for the path then
-
- /FirstY Xdef % Save the first point on the contour.
- /FirstX Xdef
-
- } { % Else, check to see if it is a real moveto
-
- 2 copy % Copy the x,y that was passed in by pathforall
- LastY ne exch % Check to see if we are really at a new point or a gratuitous
- LastX ne or { % one generated because PS stinks. So if we are, draw the dash
-
- StampDash % Draw the dash shape in the correct orientation.
-
- /FirstY Xdef % This moveto is now the first point of next dash.
- /FirstX Xdef
-
- } { % Else
- pop pop % we were passed a gratuitous moveto, ignore it.
- } ifelse
-
- } ifelse
-
- } Bdef
-
- %<FF>
- %
- % DashStroke: Procedure strokes the current path, using the dash passed in.
- %
- % frameOffset dashDict DashStroke -
- %
- % frameOffset: 1 for inside-frame, 0 for center-frame, -1 for outside-frame
- % dashDict: A valid dashing dictionary.
- %
- /DashStroke {
-
- FullGsave
-
- begin % Put the dashing dictionary on the stack.
-
- CurrRightIsOut {neg} if % if rightIsOut is set, negate the frameOffset.
- /frameOffset Xdef
-
- Shape /colorSet get SetColorSet % Set it to be the one from the shape dict. (will be restored by fullGrestore)
-
- Shape /ColorSpace get dup null ne { % Set the color space if there is one
- GXSetCSpace
- } {
- pop
- } ifelse
-
- % Compute advance for dashing:
- autoAdvance {
-
- PathLength dup advance div floor /N Xdef % Number of dashes that fit on contour.
- N div % Length divided by N = new advance.
-
- } { % Else just leave advance value on stack.
-
- advance
-
- } ifelse
-
- /@1 Xdef % Store temporarily in @1
-
-
- % Compute the array for dashing.
-
- Shape ShapeBBox % Get the shape bounding box.
-
- BoxWidths pop % Get the width of the dash shape as first entry in dash matrix.
- dup 0 eq { % But if the width is zero, we can't use it, use half advance instead
- pop % Get rid of the evil zero
- @1 2 div % replace it with half the advance width, we have nothing else to go by. Oh well.
- } if
-
- .10 mul % Take 10% of it. Moves tangent vector close to tangent at origin of dash shape.
- dup @1 exch sub % Get advance - 0.10*width as second entry in dash matrix.
- [3 1 roll] % Make the dash matrix: [.1*width advance-.1*width] - See ERS for detailed explanation.
-
- phase % Get the phase of dashing.
- breakDash {xCenter sub} if % If break dash is on, then we want dash positions to be based on center
- % of dash shape rather than 0,0 , altering phase accomplishes this.
- % We do this because Skia does it in Dashing.c
-
- setdash % Set up the PostScript dash matrix parameters.
- currentlinewidth % Save the current line width on stack.
- 0 setlinewidth % Make sure we get hairline contours.
- /strokepath 0 AvoidLimit % Get the dash contours into current path.
- setlinewidth % Restore the current line width.
- [] 0 setdash % Turn off PostScript dashing.
- /FirstX null def % Signal the start of dashing.
-
- /DashMT load
- /DashLT load
- /DashCT load
- /DashCP load
- pathforall % Stamp the dashes.
-
- FirstX null ne { % If there was any path to dash,
- StampDash % Force the last dash to draw, we stopped one short.
- } if % Else, if FirstX was null then there was no path.
-
- end
- FullGrestore newpath
-
- } Bdef
-
-
- %<FF>
- % The fill procs work as follows:
- % All of the procedures for the various fills are stored in a dictionary called FillDict
- % The key passed to QD2Fill or QD2Clip is then used to get the procedure from the dictionary.
- % The procedure is then executed.
- %
- /FillDict 7 dict dup 3 -1 roll Xdef begin % Create a dictionary, name it FillDict.
-
- % Frame Fill is just stroke.
- /Fr {
- CurrDash null eq { % If no dashing then
- CurrFrame dup 0 eq { % If inside frame
- stroke % just stroke
- pop
- } { % Else
- FillDict exch % Get the inside or outside proc from FillDict.
- -1 eq {/Of get} {/If get} ifelse
- exec
- } ifelse
-
- } { % Else
-
- CurrFrame CurrDash DashStroke % Execute the DashStroke procedure
-
- } ifelse
-
- } Bdef
-
-
- % Inside frame is done by making the current path the clip and then stroking with 2x pen.
- /If
- {gsave clip currentlinewidth 2 mul setlinewidth stroke grestore newpath} Bdef
-
-
- % Outside frame is done by making the current path combined with FullPath the eoclip and
- % then stroking with 2x pen.
- /Of
- {gsave FullPath /eoclip 0 AvoidLimit currentlinewidth 2 mul setlinewidth stroke grestore newpath} Bdef
-
-
- % Even-odd fill
- /Eo /eofill load def
-
-
- % Inverse Fill is the path combined with a full path and then even-odd filled.
- /In {FullPath eofill} Bdef
-
-
- % Winding number fill is just the normal fill operator.
- /W /fill load def
-
- /No {newpath} Bdef % No fill draws nothing.
-
- end %FillDict
-
- %<FF>
- %
- % Fill dictionary for patterns, needed only in level-1:
- % Call the PatternFill operator properly.
- %
- languagelevel 1 eq {
- /PatternFillDict 6 dict dup 3 -1 roll Xdef begin % Create the dict, name it PatternFillDict.
-
- % Frame Fill: Make the path to fill the strokepath or use dashing procedure
- /Fr {
- CurrDash null eq { % If no dashing then
- CurrFrame dup 0 eq { % If center frame
- /strokepath 0 AvoidLimit true PatternFill % just fill stroke path with pattern.
- pop
- } { % Else
- PatternFillDict exch % Get the inside or outside proc from FillDict.
- -1 eq {/Of get} {/If get} ifelse
- exec
- } ifelse
-
- } { % Else
-
- CurrFrame CurrDash DashStroke % Execute the DashStroke procedure
-
- } ifelse
-
- } Bdef
-
- % Winding-number fill:
- /W {true PatternFill} Bdef
-
- % even-odd fill
- /Eo {false PatternFill} Bdef
-
- %Inverse fill: combine the path with a TightFullPath and do even-odd fill
- /In {TightFullPath false PatternFill} Bdef
-
- % InsideFrame: Set up the clip to be the path, double the pen width, get the strokepath
- % execute the PatternFill operator, restore the clip to what it was
- /If
- {gsave clip currentlinewidth 2 mul setlinewidth strokepath
- true exch PatternFill grestore newpath} Bdef
-
- % OutsideFrame: Add the Full Path, even-odd clip, double the pen size, get the strokepath
- % execute the PatternFill operator, restore the clip to what it was.
- /Of
- {gsave TightFullPath eoclip currentlinewidth 2 mul setlinewidth strokepath
- true exch PatternFill grestore newpath} Bdef
-
- end
-
- } if % defined for level-1 only.
-
-
- %<FF>
- %
- % QD2Fill Operator. Does all Skia fills except dashing. The Imaging Engine must handle this.
- %
- % fillKey: A valid Skia fill key.
- %
- languagelevel 1 eq {
-
- /QD2Fill {
-
- CurrPat null eq { % If there is no currentpatern then
- FillDict % Get the proc from FillDict
- } { % Else
- PatternFillDict % Get it from PatternFillDict
- } ifelse
-
- exch get exec % Execute the fill procedure according to the fillKey.
-
- } Bdef
-
- } { % LEVEL TWO!!
-
- %% Level 2 version does installs the current pattern as a color space and does
- %% a fill from the regular fill dictionary instead of the patternfill dictionary.
-
-
- % So, define procedures for installing and removing the pattern as the current color space
-
- /OldColorAndSpace [] def % Make a dictionary entry for the old color and space.
- /OldMatrix matrix def % Place to store the old CTM in case we muck it up for PortAllign not
- %
- % Function: InstallPatternColorSpace
- % Routine installs the current pattern in the persistent state as the current color space.
- % The non-pattern color space can be restored by calling RestoreOldColorAndSpace
- %
- % Also, as long as we're in here, deal with pattern attributes
- %
- /InstallPatternColorSpace {
-
- CurrPat null ne { % If the current pattern in augmented state is not null
-
- % If not PortAlligned, move user space to origin of shape to fill.
-
- CurrPat begin
-
- PortMap PortAllign or {
-
- OldMatrix currentmatrix pop
- SetupPatternCTM
- SynchPatMatrix
-
- } if
-
- /OldColorAndSpace [
- currentcolor currentcolorspace % Save the current color and color space in the array.
- ] store
-
- PaintType 2 eq { % If the current pattern does not have underlying color
- currentcolor % Get the current color components on the stack
- dup type /dicttype eq {pop} if % If the current color included a pattern, get rid of it.
- } if
-
- end
-
- CurrPat setpattern % make the color and pattern the current color and pattern
-
- } if
-
- } Bdef
-
- %
- % Function: RestoreOldColorAndSpace
- % Routine restores the color and color space to what was stored in the OldColorAndSpace array.
- % It only does this if there is a pattern in the persistent state, because if there isn't then
- % InstallPatternColorSpace wouldn't have done anything.
- %
- /RestoreOldColorAndSpace {
-
- CurrPat null ne {
-
- %
- % Fix the CTM if we changed it for attributes.
- %
- CurrPat /PortAllign get CurrPat /PortMap get or {
-
- OldMatrix setmatrix
-
- } if
-
- OldColorAndSpace aload pop % Put the old color and space on the stack.
- setcolorspace setcolor % Set the grahpics state
-
- } if
-
-
- } Bdef
-
- %
- % level 2 QD2Fill routine:
- %
- /QD2Fill {
-
- %
- % Set the pattern in the PostScript graphics state if there is one
- % in our persistent state. This makes sure that our pattern is ony
- % active during the drawing of this shape and is not actually part
- % of the PostScript nested graphics state.
- %
-
- InstallPatternColorSpace
-
- FillDict % Get the fill dictionary.
- exch get exec % Execute the fill procedure according to the fillKey.
-
- % Set the PostScript graphics state back to normal color if we set pattern above.
-
- RestoreOldColorAndSpace
-
- } Bdef
-
- } ifelse % level 1 or level 2.
-
-
-
-
- %<FF>
- %
- % The GlyphPaint procedure is used for painting glyphs in All cases except
- % even-odd without pattern and inverse.
- %
- % Expects the stack to be: string fillKey
- % This procedure will paint the characters one by one to avoid building a path that
- % is too big.
- /GlyphPaint {
- FullGsave % Make sure we don't screw things up.
- exch % Get string on top of the stack.
-
- HasBold { % If there is boldness in the current style?:
- CurrBold % Get the boldness
- AugGstate /FontMapping get % We must run the boldness through the matrix
- dtransform % the font was mapped by because it was in 1pt units.
- SetBold % Make the transformed value the current boldness
- } if
-
- { % And then, for each character in the string: Draw it.
- % Stack is: fillKey, charCode
- aChar 0 3 -1 roll put % Put the character code in the string.
- dup % Duplicate the fill key for later.
- currentpoint newpath moveto % Make a new path, maintain the current point.
-
- HasBold { % If the current style contains boldness:
-
- currentpoint 3 -1 roll % Save the current point, move it behind fillKey
- aChar true GXCharPath % Get the path of the character.
- CurrCTM currentmatrix exch % Save the current transformation on the stack, behind fill key.
- CurrBold scale % scale CTM by boldness to get non-square bolding pen.
- currentlinewidth % Save the current linewidth
- exch % Move it behind the fill key.
- 1 setlinewidth % set it to 1, so scaled pen = boldness
- dup /W eq % If we are doing winding number fill
- CurrPat null eq and { % And there is no pattern.
- stroke % Stroke the bold path.
- 3 -1 roll setmatrix % Reset the CTM
- } { % else
- strokepath % Get the fillable path
- 3 -1 roll setmatrix % Reset the CTM
- dup QD2Fill % Paint the bold part of the glyph properly
- } ifelse
-
- exch setlinewidth % restore the current line width.
- 3 1 roll % Get the current point that we saved.
- moveto % Move back there to draw the rest of the glyph.
-
- } if
-
- aChar true GXCharPath
- currentpoint % Save the point where CharPath left us.
- 3 -1 roll % Stack is now: fillKey x y fillKey
- QD2Fill
- moveto % the Fill killed current point, move back there.
-
- } forall
-
- pop % Pop off the last duplicate of the fill key
- currentpoint % We now want to restore the state, but keep updated
- FullGrestore % Current point.
- moveto
-
- } Bdef
-
-
-
- %<FF>
- %
- % Show dictionary.
- % This dictionary contains routines to do all Skia fills on text.
- %
- /ShowDict 7 dict dup 3 -1 roll Xdef begin % Create a dictionary, name it ShowDict.
-
-
- % winding number is just show if no pattern and no boldness.
-
- languagelevel 1 eq {
-
- /W {CurrPat null eq HasBold not and {show} {/W GlyphPaint} ifelse} Bdef
-
- } {
-
- /W {
-
- HasBold not {
-
- % For level-2, install the pattern color space and do a show.
-
- InstallPatternColorSpace show RestoreOldColorAndSpace
-
- } {
-
- /W GlyphPaint
-
- } ifelse
-
- } Bdef
-
- } ifelse % level 1 or level 2
-
-
- % Inverse fill is path of whole string and a fill
-
- /In {true GXCharPath /In QD2Fill} Bdef
-
-
- %The rest simply invoke the main show procedure.
-
- /Fr {/Fr GlyphPaint} Bdef
-
- /If {/If GlyphPaint} Bdef
-
- /Of {/Of GlyphPaint} Bdef
-
- /Eo /W load def %% Used to be {/Eo GlyphPaint} Bdef
-
- /No {pop} Bdef
-
- end
- %
- % QD2Show operator (Used in cases where the imaging engine is not in control (like when
- % we are drawing a character in the BuildChar of a layered font)
- % When the imaging engine is in control, the proper method for text
- % display is used (although it may end up being QD2Show sometimes)
- %
- % fillKey QD2Show -
- %
- % fillKey: A valid Skia fill key.
- %
- /QD2Show {
-
- ShowDict exch get exec
-
- } Bdef
-
-
-